﻿using System.ServiceModel;
using System;
using System.Collections.Generic;
using System.Collections;
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession,ConcurrencyMode=ConcurrencyMode.Multiple)]
public class Service : IService
{
    const int AreaNum = 36;
    int position;
    Area currentArea;
    User current;//현재 접속중인 유저
    ICallback callback;
    static bool gaming=false;
    //static SynchronizedKeyedCollection<string, User> userList = new UserTable();//접속하고 있는 유저.//아이디로 접근시 이걸 쓰고...
    //순차적인 접근을 많이 이용하기 때문... SynchronizedCollection을 사용하겠음.
    static SynchronizedCollection<User> userList = new SynchronizedCollection<User>();
    static Area[] GameBoard;
    public void Start()
    {
        callback = OperationContext.Current.GetCallbackChannel<ICallback>();
    }
    public User[] Login(string id)
    {
        if (gaming)
        {
            callback.CallBackError("게임중입니다.");
            return null;
        }
        lock (userList.SyncRoot)
        {
            foreach (User user in userList)
            {
                if (user.Id == id)
                {
                    return null;
                }
            }
            current = new User();
            current.Id = id;
            userList.Add(current);
            current.Callback = callback;
            User[] userArray=new User[userList.Count];
            userList.CopyTo(userArray, 0);
            callback.CallBackMessage(id + "님의 로그인 성공");
            return userArray;
        }
    }
    public void Quit()
    {
        if (current == null)
        {
            return;
        }
        lock (userList.SyncRoot)
        {
            userList.Remove(current);
            foreach (User user in userList)
            {
                user.Callback.CallBackMessage(this.current.Id + "님이 나갑니다.");
            }
        }

        //게임중이면 다 재산 같은 거 다 없앰.
        if (gaming)
        {
            current.Money = 0;

            //...
        }
    }
    static bool Gaming
    {
        set { gaming = value; }
        get { return gaming; }
    }
    public void InitGame()
    {
        
        /*    lock (room.UserSync)//게임의 초기화때 유저가 들어오거나 나가거나 막는 것.
            {
                room.Playing = true;//게임시작함.
                //게임관련초기화
                room.Init();//방안에서의 초기화
            }
            */
        GameBoard = new Area[AreaNum];
        GameBoard[0] = new EventZone("출발지");

        GameBoard[1] = new Estate("한국", "서울", 5000);
        GameBoard[2] = new Estate("일본", "도코", 7000);
        GameBoard[3] = new Estate("중국", "북경", 4000);
        GameBoard[4] = new Estate("인도", "뉴델리", 2100);
        GameBoard[5] = new Estate("태국", "방콕", 3800);
        GameBoard[6] = new Estate("말레이시아", "콸라룸푸", 3700);
        GameBoard[7] = new Estate("싱가포르", "싱가포르", 5300);
        GameBoard[8] = new Estate("필리핀", "마닐라", 3800);

        GameBoard[9] = new EventZone("무인도");

        GameBoard[10] = new Estate("호주", "시드니", 5000);
        GameBoard[11] = new Estate("칠레", "산티아고", 2700);
        GameBoard[12] = new Estate("아르헨티나", "부에노스아레스", 3000);
        GameBoard[13] = new Estate("브라질", "상파울루", 3100);
        GameBoard[14] = new EventZone("이벤트카드");
        GameBoard[15] = new Estate("멕시코", "멕시코시티", 3500);
        GameBoard[16] = new Estate("쿠바", "아바나", 1800);
        GameBoard[17] = new Estate("미국", "뉴옥", 7800);

        GameBoard[18] = new EventZone("우주정거장");

        GameBoard[19] = new Estate("러시아", "모스크바", 4300);
        GameBoard[20] = new Estate("폴란드", "바르샤바", 3700);
        GameBoard[21] = new Estate("영국", "런던", 5800);
        GameBoard[22] = new Estate("프랑스", "파리", 4500);
        GameBoard[23] = new Estate("스페인", "마드리드", 4700);
        GameBoard[24] = new Estate("포루투칼", "리스본", 4300);
        GameBoard[25] = new Estate("독일", "베를린", 4800);
        GameBoard[26] = new Estate("이탈리아", "로마", 5000);

        GameBoard[27] = new EventZone("복지기금출금");

        GameBoard[28] = new Estate("튀니지", "튀니스", 2800);
        GameBoard[29] = new Estate("알제리", "알제", 2700);
        GameBoard[30] = new Estate("모르코", "카사블랑카", 2400);
        GameBoard[31] = new Estate("수단", "히트룸", 2300);
        GameBoard[32] = new EventZone("복지기금입금");
        GameBoard[33] = new Estate("요르단", "암만", 3300);
        GameBoard[34] = new Estate("UAE", "두바이", 5000);
        GameBoard[35] = new Estate("터키", "이스탄불", 2700);

        foreach (User user in userList)
            user.Money = 200000;//20만달러로 시작
        
    }
//    Room room;//현재 룸
    
    
    //모든 유저
//    static RoomTable roomList = new RoomTable();//생성되어 있는 방
/*    public User Login(string id,string password)
    {
        try
        {
            User user = userList[id];
            if (user.Password == password)
            {
                return user;
            }
            return null;//나중에 콜백으로 비밀번호가 틀림.
        }
        catch (KeyNotFoundException)
        {
            return null;//아이디를 찾지 못 했을 때...
        }
    }
    public bool Join(string id, string password, string nickname)//테스트 통과
    {
        user = new User();
        user.Id = id;
        try
        {
            lock (userList.SyncRoot) { userList.Add(user); }
        }
        catch (ArgumentException)
        {
            return false;
        }
        user.Password = password;
        user.Nickname = nickname;
        return true;
    }
    
    public void CreateRoom(int no,string title)//제한없이 받음.
    {
        Room room;
        lock (roomList.SyncRoot)
        {
            while (roomList.Contains(no))
                no++;
            room = new Room();
            room.No = no;
            room.Title = title;
            roomList.Add(room);
        }
        this.room = room;
    }

    public bool JoinRoom(int no)
    {
        try
        {
            room = roomList[no];
            lock (room.UserSync)
            {
                if (room.Playing)
                {
                    return false;//게임중입니다.
                }
                room.Join(user);
            }
        }
        catch (KeyNotFoundException)
        {
            return false;//방이 없습니다.
        }
        catch (ArgumentException)
        {
            return false;//방에 같은 아이디가 있습니다.
        }
        return true;
    }

    public void QuitRoom()
    {
        throw new NotImplementedException();
    }
    */
    
    

    public bool RollDice()
    {
        Random random = new Random();
        int firstDice=random.Next(8);
        int secondDice = random.Next(8);
        MoveAvatar(firstDice + secondDice);
        if (firstDice == secondDice)
        {
            return true;
        }
        return false;
    }

    public void MoveAvatar(int i)
    {
        position += i;
        position %= AreaNum;
        currentArea = GameBoard[position];
    }

    public void Buy()
    {
        if (currentArea is Estate)
        {
            if (current.BuyEstate((currentArea as Estate)))
            {
                callback.CallBackError("사지 못 했습니다.");
                return;
            }
            callback.CallBackMessage(currentArea.Title + "샀습니다.");
            return;
        }
        callback.CallBackError("오류입니다. Buy EventZone");
        return;
    }

    public void Sell()
    {
        if (currentArea is Estate)
        {
            Estate estate = currentArea as Estate;
            if (estate.Onwer.Id == current.Id)
            {
                current.SellEstate(estate);
                callback.CallBackMessage("팔았습니다.");
                return;
            }
            else
            {
                callback.CallBackError("주인이 아닌 땅입니다.");
                return;
            }
        }
        callback.CallBackError("팔수 없는 지역입니다.");
    }

    public void Display()
    {
        throw new NotImplementedException();
    }
}
public class UserTable : SynchronizedKeyedCollection<string, User>
{
    protected override string GetKeyForItem(User user)
    {
        return user.Id;
    }
}